package com.ts.view

import android.content.Context
import android.graphics.SurfaceTexture
import android.opengl.GLES11Ext
import android.opengl.GLES20
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.util.Log
import com.ts.audiocamera.R
import com.ts.camera2.CameraUtil
import com.ts.utils.MediaUtils
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class CameraRender( var mContext: Context,var mCameraSurfaceView:CameraSurfaceView) :GLSurfaceView.Renderer {

    var mSurfaceTexture:SurfaceTexture?=null

    var mCameraUtil:CameraUtil
    /**
     * 每行前两个值为顶点坐标，后两个为纹理坐标
     */

    val VERTEX_DATA: FloatArray = floatArrayOf(
        1f, 1f, 1f, 1f,
        -1f, 1f, 0f, 1f,
        -1f, -1f, 0f, 0f,
        1f, 1f, 1f, 1f,
        -1f, -1f, 0f, 0f,
        1f, -1f, 1f, 0f
    )

    init {

        mCameraUtil=CameraUtil();

    }


    /**
     * 创建 FloatBuffer 数组 (防止内存回收)
     * @param vertexData float 数组
     * @return FloatBuffer
     */
    private fun createBuffer(vertexData: FloatArray): FloatBuffer {
        val buffer = ByteBuffer.allocateDirect(vertexData.size * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        buffer.put(vertexData, 0, vertexData.size).position(0)
        return buffer
    }

//    private val mFBOIds = IntArray(1)
    private var mOESTextureId = -1
    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        mOESTextureId=createTexture();
        val vertexShaderSource = MediaUtils.readRawTextFile(mContext, R.raw.base_vertex_shader);
        val fragmentShaderSource = MediaUtils.readRawTextFile(mContext, R.raw.base_fragment_shader)

        createPrograme(vertexShaderSource,fragmentShaderSource)
//        GLES30.glGenFramebuffers(1, mFBOIds, 0)
//        GLES30.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFBOIds.get(0))

        vPosition =GLES30.glGetAttribLocation(program,"aPosition")
         vCoord=GLES30.glGetAttribLocation(program,"aTextureCoordinate")
         vMatrix= GLES30.glGetUniformLocation(program,"uTextureMatrix")
         uTextureSamplerLocation = GLES20.glGetUniformLocation(
            program,
            "uTextureSampler"
        )

    }
    var vPosition=-1;
    var vCoord=-1;
    var program=-1

    var vMatrix=-1;
    var uTextureSamplerLocation=0;
    private fun createPrograme(vertexShaderSource:String,fragmentShaderSource:String) {
        val vShader=GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER);
        GLES30.glShaderSource(vShader,vertexShaderSource);
        GLES30.glCompileShader(vShader);

        val fShader=GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER);
        GLES30.glShaderSource(fShader,fragmentShaderSource);
        GLES30.glCompileShader(fShader);

         program=GLES30.glCreateProgram();
        GLES30.glAttachShader(program,vShader);
        GLES30.glAttachShader(program,fShader);
        GLES30.glLinkProgram(program)
        GLES30.glUseProgram(program);


    }
    private var mDataBuffer: FloatBuffer? = null
    fun createTexture():Int{
        //创建纹理
        val textures=IntArray(1);

        GLES30.glGenTextures(1,textures,0)


        //将此纹理绑定到外部纹理上
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            textures[0])

        //设置纹理过滤参数
        GLES30.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST.toFloat()
        )
        GLES30.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR.toFloat()
        )
        GLES30.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE.toFloat()
        )
        GLES30.glTexParameterf(
            GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE.toFloat()
        )
        //解除纹理绑定
        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0)
        return textures[0];
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height);
    }
    private val transformMatrix = FloatArray(16)
    override fun onDrawFrame(gl: GL10?) {
        Log.e(TAG,"onDrawFrame")
        mSurfaceTexture?.updateTexImage()
        //获取外部纹理的矩阵，用来确定纹理的采样位置，没有此矩阵可能导致图像翻转等问题
        mSurfaceTexture?.getTransformMatrix(transformMatrix)
        initSurfaceTexture();

        GLES30.glClearColor(0.0f,0.0f,0.0f,0.0f)

        GLES30.glActiveTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES)

        GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,mOESTextureId);
        //将纹理矩阵传给片段着色器
        //将此纹理单元床位片段着色器的uTextureSampler外部纹理采样器
        GLES30.glUniform1i(uTextureSamplerLocation, 0)

        GLES30.glUniformMatrix4fv(
            vMatrix, 1,
            false, transformMatrix, 0
        )

        if (mDataBuffer==null){
            mDataBuffer=createBuffer(VERTEX_DATA)
        }
        //顶点坐标从位置0开始读取
        mDataBuffer?.position(0)
        GLES30.glEnableVertexAttribArray(0)
        GLES30.glVertexAttribPointer(
            vPosition, 2, GLES30.GL_FLOAT,
            false, 16, mDataBuffer
        )
        GLES30.glEnableVertexAttribArray(1)
        //纹理坐标从位置2开始读取
        mDataBuffer?.position(2)
        GLES30.glEnableVertexAttribArray(1)
        GLES30.glVertexAttribPointer(
            vCoord, 2, GLES30.GL_FLOAT,
            false, 16, mDataBuffer
        )
        GLES30.glEnableVertexAttribArray(1)
        //glDrawElements(GL_TRIANGLE_FAN, 6,GL_UNSIGNED_INT, 0);
        //glDrawArrays(GL_TRIANGLE_FAN, 0 , 6);
        //绘制两个三角形（6个顶点）
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6)

        //glDrawArrays(GL_TRIANGLES, 3, 3);
//        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0)
    }


    private  val TAG = "CameraRender"

    fun initSurfaceTexture(){

        if (mSurfaceTexture!=null){
            return
        }
        mSurfaceTexture=SurfaceTexture(mOESTextureId)
        mSurfaceTexture?.setOnFrameAvailableListener {
            Log.e(TAG,"setOnFrameAvailableListener")
            mCameraSurfaceView.requestRender()
        }
        mCameraUtil.openCamera(mContext,1080,1920,mSurfaceTexture);


    }
}